using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.WebControls.WebParts;

namespace SmartPart
{
    /// <summary>
    /// Description of the toolpart. Override the GetToolParts method in your WebPart
    /// class to invoke this toolpart. To establish a reference to the Web Part 
    /// the user has selected, use the ParentToolPane.SelectedWebPart property.
    /// </summary>
    public class UserControlPropertiesToolpart : Microsoft.SharePoint.WebPartPages.ToolPart
    {
        private ArrayList _properties = new ArrayList();

        public int NumberOfProperties
        {
            get
            {
                return _properties.Count;
            }
        }


        /// <summary>
        /// Constructor for the class.
        /// </summary>
        public UserControlPropertiesToolpart(Control control)
        {
            //Check for description attribute
            object[] classAttributes = control.GetType().GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), true);
            if (classAttributes.Length > 0)
                this.Title = ((System.ComponentModel.DescriptionAttribute)classAttributes[0]).Description;
            else
                this.Title = control.GetType().Name;

            classAttributes = control.GetType().GetCustomAttributes(typeof(WebDisplayNameAttribute), true);
            if (classAttributes.Length > 0)
                this.Title = ((WebDisplayNameAttribute)classAttributes[0]).DisplayName;

            Type controlType = control.GetType();
            PropertyInfo[] props = controlType.GetProperties();

            foreach (PropertyInfo pi in props)
            {

                object[] attributes = pi.GetCustomAttributes(typeof(System.ComponentModel.BrowsableAttribute), false);

                if (pi.CanWrite && pi.CanRead && attributes.Length > 0 && ((System.ComponentModel.BrowsableAttribute)attributes[0]).Browsable)
                {  //pi.DeclaringType != typeof(UserControl) && pi.DeclaringType != typeof(Control)) {
                    _properties.Add(pi);
                }

                attributes = pi.GetCustomAttributes(typeof(WebBrowsableAttribute), false);

                if (pi.CanWrite && pi.CanRead && attributes.Length > 0 && ((WebBrowsableAttribute)attributes[0]).Browsable)
                {  //pi.DeclaringType != typeof(UserControl) && pi.DeclaringType != typeof(Control)) {
                    _properties.Add(pi);
                }
            }

            if (_properties.Count == 0)
                this.FrameState = FrameState.Minimized;
        }

        ///	<summary>
        ///	This method is called by the ToolPane object to apply property changes to the selected Web Part. 
        ///	</summary>
        public override void ApplyChanges()
        {
            SmartPart ucc = (SmartPart)this.ParentToolPane.SelectedWebPart;
            Control control = ucc.GetUserControl();
            if (control != null)
            {
                Type controlType = control.GetType();

                foreach (PropertyInfo pi in _properties)
                {
                    try
                    {

                        string val = Page.Request.Form["input" + this.UniqueID + pi.Name];
                        object v = null;

                        switch (pi.PropertyType.FullName)
                        {
                            case "System.String":
                                v = Convert.ToString(val);
                                break;
                            case "System.Double":
                                try
                                {
                                    v = Convert.ToDouble(val);
                                }
                                catch
                                {
                                    v = Double.NaN;
                                }
                                break;
                            case "System.Int32":
                                try
                                {
                                    v = Convert.ToInt32(val);
                                }
                                catch
                                {
                                    v = 0;
                                }
                                break;
                            case "System.Boolean":
                                v = val == "on";
                                break;
                        }

                        object[] attributes = pi.GetCustomAttributes(typeof(DefaultValueAttribute), false);

                        if (attributes.Length > 0 && ((DefaultValueAttribute)attributes[0]).Value.Equals(v))
                        {
                            ucc.UserControlProperties.Remove(pi.Name);
                            pi.SetValue(control, v, null);
                        }
                        else
                        {
                            ucc.UserControlProperties[pi.Name] = v;
                        }
                    }
                    catch { }
                }
                ucc.RefreshPropertyValues();
            }
        }

        /// <summary>
        ///	If the ApplyChanges method succeeds, this method is called by the ToolPane object
        ///	to refresh the specified property values in the toolpart user interface.
        /// </summary>
        public override void SyncChanges()
        {
            // Sync with the new property changes here.
        }

        /// <summary>
        ///	This method is called by the ToolPane object if the user discards changes to the selected Web Part. 
        /// </summary>
        public override void CancelChanges()
        {
        }


        /// <summary>
        /// Render this tool part to the output parameter specified.
        /// </summary>
        /// <param name="output">The HTML writer to write out to </param>
        protected override void RenderToolPart(HtmlTextWriter output)
        {
            SmartPart ucc = (SmartPart)this.ParentToolPane.SelectedWebPart;

            Control control = ucc.GetUserControl();
            if (control != null)
            {
                Type controlType = control.GetType();

                foreach (PropertyInfo pi in _properties)
                {
                    try
                    {
                        string description = pi.Name;

                        //Check for DescriptionAttribute
                        object[] attributes = pi.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
                        if (attributes.Length > 0)
                            description = ((System.ComponentModel.DescriptionAttribute)attributes[0]).Description;

                        attributes = pi.GetCustomAttributes(typeof(WebDisplayNameAttribute), false);
                        if (attributes.Length > 0)
                            description = ((WebDisplayNameAttribute)attributes[0]).DisplayName;

                        object val = pi.GetValue(control, null);
                        if (ucc.UserControlProperties.ContainsKey(pi.Name))
                        {
                            val = ucc.UserControlProperties[pi.Name];
                        }
                        if (pi.PropertyType.FullName == "System.Boolean")
                        {
                            if ((bool)val)
                            {
                                val = "checked";
                            }
                            else
                            {
                                val = "";
                            }
                            output.Write("<p>&nbsp;<input type='checkbox' " + val.ToString() + " name='input" + this.UniqueID + pi.Name + "' />" + description + "</p>");
                        }
                        else
                        {
                            output.Write("<p>");
                            output.Write(description);
                            output.Write("<br>");
                            if (val == null)
                            {
                                val = "";
                            }
                            output.Write("&nbsp;<input value='" + val.ToString() + "' name='input" + this.UniqueID + pi.Name + "' /></p>");
                        }
                    }
                    catch { }
                }
            }
        }

    }
}

